4. 도커 개요2

2.2. 다양한 컨테이너 실행 방법

핵심 개념

컨테이너는 기본적으로 호스트와 격리된 환경에서 실행되지만, 실무에서는 데이터 공유, 네트워크 통신, 여러 컨테이너 조합 등 다양한 요구사항이 있음.

컨테이너 실행 고급 기능:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[기본 격리 환경]
    ↓
[확장 기능]
    │
    ├─ 파일 공유
    │  └─ 바인드 마운트, 볼륨
    │
    ├─ 네트워크 공개
    │  └─ 포트 포워딩
    │
    └─ 다중 컨테이너 관리
       └─ Docker Compose

목표:
→ 데이터 영속성 확보
→ 외부 통신 활성화
→ 컨테이너 간 협업

2.2.1. 호스트와 컨테이너의 파일 공유와 데이터 유지

문제 상황

컨테이너 파일시스템의 한계:

컨테이너 격리로 인한 제약:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[호스트 OS]
    ├─ /home/user/data
    └─ /var/log/app
        ✗ 컨테이너에서 접근 불가

[컨테이너]
    ├─ /app/data
    └─ /var/log
        ✗ 컨테이너 삭제 시 데이터 손실

문제점:
→ 컨테이너는 독립된 루트 파일시스템 보유
→ 컨테이너 종료/삭제 시 내부 데이터 소멸
→ 호스트 파일에 직접 접근 불가
→ 컨테이너 간 파일 공유 불가

해결 방법1: 바인드 마운트

호스트 파일/디렉터리를 컨테이너에 연결:

바인드 마운트 개념:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[호스트 OS]
    │
    └─ /tmp/test/
       └─ file.txt
          ↓ 마운트
       [컨테이너]
          │
          └─ /mnt/
             └─ file.txt (동일 파일)

특징:
→ 호스트와 컨테이너가 같은 파일 공유
→ 양방향 동기화 (읽기/쓰기)
→ 컨테이너 삭제해도 호스트 파일 유지

바인드 마운트 실습:

# 1. 호스트에 테스트 디렉터리 생성
mkdir C:\tmp\test
echo "Hello from host" > C:\tmp\test\host.txt

# 2. 바인드 마운트로 컨테이너 실행
docker run -it --name bind-test -v C:\tmp\test:/mnt:ro ubuntu:22.04 /bin/bash

명령어 구조:

docker run -v 옵션 설명:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

docker run -v /tmp/test:/mnt:ro ubuntu:22.04
           │     │        │    │
           │     │        │    └─ 마운트 옵션
           │     │        │       ro: 읽기 전용
           │     │        │       rw: 읽기/쓰기 (기본값)
           │     │        │
           │     │        └─ 컨테이너 내부 경로
           │     │           (마운트 포인트)
           │     │
           │     └─ 호스트 경로
           │        (소스 디렉터리)
           │
           └─ 볼륨/바인드 마운트 옵션

경로 규칙:
→ 절대 경로 사용 필수
→ 호스트:컨테이너 순서
→ 콜론(:)으로 구분

컨테이너 내부에서 확인:

# 컨테이너 쉘에서 실행
cd /mnt
ls
# 출력: host.txt

cat host.txt
# 출력: Hello from host

# 읽기 전용 확인
cat "test" > /mnt/test.txt
# 오류: Read-only file system

바인드 마운트 활용 시나리오:

실무 사용 예시:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[개발 환경]
docker run -v ${PWD}:/app myapp
    │
    └─ 소스 코드 실시간 반영
       코드 수정 즉시 컨테이너에 반영

[로그 수집]
docker run -v /var/log/app:/logs myapp
    │
    └─ 컨테이너 로그를 호스트에 저장
       모니터링 도구에서 로그 분석

[설정 파일 주입]
docker run -v ./config.yml:/etc/app/config.yml:ro myapp
    │
    └─ 환경별 설정 동적 주입
       이미지 재빌드 없이 설정 변경

해결 방법2: 볼륨

도커가 관리하는 영속 스토리지:

볼륨 vs 바인드 마운트:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[바인드 마운트]
호스트 경로: /home/user/data
    ↓ 직접 지정
컨테이너 경로: /app/data

특징:
→ 호스트 경로를 명시적으로 지정
→ 파일/디렉터리 모두 가능
→ 호스트에서 직접 접근 가능

[볼륨]
볼륨 이름: my-volume
    ↓ 도커가 관리
호스트 경로: /var/lib/docker/volumes/my-volume/_data
    ↓ 자동 마운트
컨테이너 경로: /app/data

특징:
→ 도커가 위치 자동 관리
→ 디렉터리만 가능
→ docker volume 명령어로 관리
→ 컨테이너 간 공유 용이

볼륨 생성 및 사용:

# 1. 명시적 볼륨 생성 (선택사항)
docker volume create shared-vol

# 2. 볼륨 목록 확인
docker volume ls

볼륨 마운트 실습:

# 첫 번째 컨테이너에서 데이터 작성
docker run -it --name test-vol -v shared-vol:/mnt ubuntu:22.04 /bin/bash

컨테이너 내부에서 작업:

# shared-vol 볼륨에 파일 작성
echo "Hello" > /mnt/hello

# 컨테이너 로컬에만 파일 작성
echo "test" > /test

# 확인
ls /mnt  # hello 파일 존재
ls /     # test 파일 존재

다른 컨테이너에서 볼륨 공유 확인:

# 동일한 볼륨을 읽기 전용으로 마운트
docker run -it --name test-vol-2 -v shared-vol:/mnt:ro ubuntu:22.04 /bin/bash

두 번째 컨테이너 내부:

# 첫 번째 컨테이너에서 작성한 파일 읽기
cat /mnt/hello
# 출력: Hello

# test 파일은 보이지 않음 (첫 번째 컨테이너 로컬 파일)
cat /test
# 오류: No such file or directory

# 읽기 전용 확인
echo "hi" > /mnt/hi
# 오류: Read-only file system

볼륨 공유 메커니즘:

여러 컨테이너의 볼륨 공유:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Docker 볼륨: shared-vol]
    │
    ├─→ [컨테이너 1: test-vol]
    │   └─ /mnt (읽기/쓰기)
    │      └─ hello 파일 작성
    │
    └─→ [컨테이너 2: test-vol-2]
        └─ /mnt (읽기 전용)
           └─ hello 파일 읽기

데이터 흐름:
1. test-vol에서 /mnt/hello 작성
2. shared-vol에 저장
3. test-vol-2에서 /mnt/hello 읽기 가능

장점:
→ 컨테이너 간 데이터 공유
→ 컨테이너 삭제해도 볼륨 유지
→ 데이터 영속성 보장

볼륨 생명주기 관리

볼륨 정리 작업:

# 컨테이너 중지
docker stop test-vol test-vol-2

# 컨테이너 삭제
docker rm test-vol test-vol-2

# 볼륨 목록 확인 (여전히 존재)
docker volume ls
# 출력: shared-vol 존재

# 볼륨 상세 정보
docker volume inspect shared-vol

# 볼륨 삭제
docker volume rm shared-vol

# 미사용 볼륨 일괄 삭제
docker volume prune

볼륨 생명주기:

볼륨 라이프사이클:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[생성]
docker volume create my-vol
또는
docker run -v my-vol:/data (자동 생성)
    ↓
[사용]
여러 컨테이너에 마운트 가능
데이터 읽기/쓰기
    ↓
[유지]
컨테이너 삭제해도 볼륨 유지
    ↓
[삭제]
docker volume rm my-vol (명시적)
또는
docker volume prune (미사용)

핵심:
→ 컨테이너와 독립적인 생명주기
→ 명시적으로 삭제하기 전까지 유지
→ 데이터 영속성 확보

바인드 마운트 vs 볼륨 선택 가이드:

사용 시나리오별 선택:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[바인드 마운트 사용]
✓ 개발 환경 (소스 코드 실시간 반영)
✓ 로그 파일 (호스트에서 직접 확인)
✓ 설정 파일 (특정 위치 지정 필요)
✓ 호스트 경로가 명확할 때

예시:
docker run -v ${PWD}/src:/app/src myapp

[볼륨 사용]
✓ 데이터베이스 데이터 (영속성)
✓ 컨테이너 간 데이터 공유
✓ 프로덕션 환경 데이터 저장
✓ 도커가 위치 관리해도 될 때

예시:
docker run -v db-data:/var/lib/mysql mysql

추천:
→ 개발: 바인드 마운트
→ 프로덕션: 볼륨
용어 정리

마운트 (Mount): 파일시스템을 특정 경로에 연결하는 것. 외부 저장소를 디렉터리처럼 사용 가능하게 함.

바인드 마운트 (Bind Mount): 호스트의 특정 경로를 컨테이너에 직접 연결. 호스트 파일 변경 시 컨테이너에 즉시 반영됨.

볼륨 (Volume): 도커가 관리하는 데이터 저장 공간. /var/lib/docker/volumes/에 위치함.

영속성 (Persistence): 데이터가 프로세스 종료 후에도 유지되는 특성. 컨테이너 삭제 후에도 데이터 보존됨.


2.2.2. 컨테이너 포트를 호스트에서 공개하기

네트워크 격리 문제

컨테이너의 독립 네트워크:

컨테이너 네트워크 격리:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[호스트 OS]
    ├─ IP: 192.168.1.100
    └─ Port: 8080
        ✗ 컨테이너가 사용 불가

[컨테이너]
    ├─ IP: 172.17.0.2 (독립적)
    └─ Port: 80
        ✗ 외부에서 접근 불가

문제:
→ 컨테이너는 독립된 네트워크 인터페이스 보유
→ 호스트와 다른 IP 주소 할당
→ 기본적으로 외부에서 컨테이너 접근 불가

포트 포워딩 (Port Publishing)

호스트 포트와 컨테이너 포트 연결:

포트 공개 메커니즘:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[외부 클라이언트]
    ↓ 요청
http://localhost:8080
    ↓
[호스트: 127.0.0.1:8080]
    ↓ 포트 포워딩
[컨테이너: 172.17.0.2:80]
    ↓
[NGINX 서버]
    ↓ 응답
[외부 클라이언트]

동작 원리:
→ 호스트 포트로 들어온 트래픽
→ 도커가 컨테이너 포트로 전달
→ 컨테이너에서 응답 생성
→ 도커가 호스트를 통해 응답 반환

포트 공개 실습

NGINX 웹 서버 실행:

# NGINX 컨테이너를 백그라운드로 실행
docker run -d --name nginx-sample -p 127.0.0.1:8080:80 nginx:1.25

명령어 구조:

docker run -p 옵션 설명:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

docker run -d -p 127.0.0.1:8080:80 nginx:1.25
              │       │      │    │
              │       │      │    └─ 컨테이너 포트
              │       │      │       (NGINX 리스닝 포트)
              │       │      │
              │       │      └─ 호스트 포트
              │       │         (외부 접근 포트)
              │       │
              │       └─ 바인드 IP
              │          (접근 허용 주소)
              │
              └─ 포트 공개 옵션

-d: Detached 모드 (백그라운드 실행)

바인드 IP 옵션:
├─ 127.0.0.1: 로컬호스트만 (보안)
├─ 0.0.0.0: 모든 인터페이스 (외부 접근)
└─ 생략: 0.0.0.0 기본값

다양한 포트 매핑 형식:

포트 매핑 패턴:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[기본 형식]
-p 127.0.0.1:8080:80
→ 127.0.0.1의 8080포트를 컨테이너 80포트로 연결

[IP 생략]
-p 8080:80
→ 모든 IP의 8080포트를 컨테이너 80포트로 연결
→ 외부에서도 접근 가능 (주의!)

[호스트 포트 자동 할당]
-p 80
→ 컨테이너 80포트를 호스트의 임의 포트로 연결
→ docker port 명령어로 확인

[여러 포트 공개]
-p 8080:80 -p 8443:443
→ HTTP(80), HTTPS(443) 동시 공개

[UDP 포트]
-p 53:53/udp
→ DNS 등 UDP 프로토콜

접속 확인:

# PowerShell에서 웹 요청 (보안 경고 없이)
Invoke-WebRequest -Uri http://127.0.0.1:8080 -UseBasicParsing

# 또는 curl.exe 사용
curl.exe http://127.0.0.1:8080

# 브라우저로 접속
# http://127.0.0.1:8080

포트 매핑 확인:

# 컨테이너의 포트 매핑 정보 확인
docker port nginx-sample

# 출력 예시:
# 80/tcp -> 127.0.0.1:8080

정리 작업:

# 컨테이너 중지 및 삭제
docker stop nginx-sample
docker rm nginx-sample

보안 고려사항

포트 공개 시 주의사항:

보안 베스트 프랙티스:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[위험한 설정]
docker run -p 3306:3306 mysql
    ↓
모든 IP에서 MySQL 접근 가능
외부 공격에 노출

[안전한 설정]
docker run -p 127.0.0.1:3306:3306 mysql
    ↓
로컬호스트에서만 접근 가능
외부 차단

권장사항:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[개발 환경]
→ 127.0.0.1 바인딩 사용
→ 필요한 포트만 공개
→ 테스트 후 즉시 중지

[프로덕션 환경]
→ 리버스 프록시 사용 (NGINX, Traefik)
→ 방화벽 규칙 설정
→ TLS/SSL 인증서 적용
→ 최소 권한 원칙

예시:
# 개발
docker run -p 127.0.0.1:8080:80 myapp

# 프로덕션
docker run -p 127.0.0.1:8080:80 myapp
+ NGINX 리버스 프록시
+ Certbot SSL

실무 네트워크 구성:

프로덕션 네트워크 아키텍처:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[인터넷]
    ↓
[NGINX 리버스 프록시] :80, :443
    ↓ 내부 네트워크
[Docker 컨테이너들]
    ├─ Web App: 127.0.0.1:8080
    ├─ API Server: 127.0.0.1:3000
    └─ Database: 127.0.0.1:5432 (공개 안 함)

계층화:
1. 외부: NGINX만 공개 (80, 443)
2. 내부: 컨테이너들은 localhost에만 바인딩
3. DB: 포트 공개 없이 도커 네트워크로만 통신
용어 정리

포트 포워딩 (Port Forwarding): 특정 포트로 들어온 트래픽을 다른 포트로 전달. 호스트 → 컨테이너 통신 연결에 사용됨.

리버스 프록시 (Reverse Proxy): 클라이언트 요청을 받아 내부 서버로 전달하는 서버. NGINX, Traefik 등이 대표적임.

TLS/SSL: TLS(Transport Layer Security)는 네트워크 통신 암호화 프로토콜. SSL(Secure Sockets Layer)은 TLS의 이전 명칭이며 현재는 TLS를 사용함.

Detached 모드 (-d): 컨테이너를 백그라운드에서 실행. 터미널 점유 없이 실행 지속됨.


2.2.3. 컴포즈: 여러 컨테이너를 한꺼번에 관리하기

Docker Compose 개념

다중 컨테이너 관리의 필요성:

컨테이너 조합의 복잡성:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[단일 명령어 방식의 한계]
docker run -d --name db mysql
docker run -d --name web --link db myapp
docker run -d --name nginx -p 80:80 nginx

문제점:
→ 실행 순서 고려 필요
→ 각 컨테이너별 명령어 개별 실행
→ 설정 관리 어려움
→ 재현성 낮음

[Compose 방식]
docker compose up
    ↓
모든 컨테이너 자동 실행
올바른 순서 보장
설정 파일로 관리

장점:
→ 명령어 1개로 전체 관리
→ YAML 파일로 설정 버전 관리
→ 개발/테스트 환경 재현 용이

Docker Compose 작업 흐름:

Compose 사용 흐름:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[1단계] compose.yml 작성
    ↓
services:
  web:
    image: myapp
  db:
    image: mysql

[2단계] 빌드 (필요시)
    ↓
docker compose build

[3단계] 실행
    ↓
docker compose up

[4단계] 중지 및 삭제
    ↓
docker compose down

핵심 명령어:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
build  : 이미지 빌드
up     : 컨테이너 생성 및 시작
down   : 컨테이너 중지 및 삭제
ps     : 컨테이너 상태 확인
logs   : 로그 확인

Compose vs Kubernetes

스코프 차이:

도구 비교:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[Docker Compose]
범위: 단일 머신
대상: 소규모 애플리케이션
용도: 개발, 테스트, 소규모 배포

[호스트 머신]
    ├─ 컨테이너 1
    ├─ 컨테이너 2
    └─ 컨테이너 3

특징:
→ 설정 간단
→ 로컬 개발에 최적
→ 학습 곡선 낮음

[Kubernetes]
범위: 여러 머신 (클러스터)
대상: 대규모 분산 시스템
용도: 프로덕션 운영

[클러스터]
    ├─ 노드 1
    │   ├─ Pod A
    │   └─ Pod B
    ├─ 노드 2
    │   ├─ Pod C
    │   └─ Pod D
    └─ 노드 3
        └─ Pod E

특징:
→ 고가용성
→ 자동 스케일링
→ 학습 곡선 높음

선택 기준:
→ 개발/테스트: Docker Compose
→ 프로덕션 소규모: Docker Compose
→ 프로덕션 대규모: Kubernetes

WordPress + MariaDB 실습

프로젝트 준비:

# 1. 프로젝트 디렉터리 생성
mkdir wordpress
cd wordpress

Compose 파일 작성:

# 2. compose.yml 파일 생성
@"
services:
  wordpress:
    image: wordpress:6.3
    restart: always
    ports:
      - 127.0.0.1:8080:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - wordpress:/var/www/html

  db:
    image: mariadb:11.1
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql

volumes:
  wordpress:
  db:
"@ | Set-Content compose.yml -Encoding UTF8

Compose 파일 구조 분석:

compose.yml 구조:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[최상위 요소]
    │
    ├─ services
    │  └─ 실행할 컨테이너 정의
    │
    └─ volumes
       └─ 공유 볼륨 정의

[services 섹션]
    │
    ├─ wordpress
    │  ├─ image: 사용할 이미지
    │  ├─ restart: 재시작 정책
    │  ├─ ports: 포트 매핑
    │  ├─ environment: 환경 변수
    │  └─ volumes: 볼륨 마운트
    │
    └─ db
       ├─ image: mariadb:11.1
       ├─ environment: DB 설정
       └─ volumes: 데이터 저장

[volumes 섹션]
    ├─ wordpress: 웹 파일 저장
    └─ db: 데이터베이스 저장

주요 설정 상세 설명:

설정 항목 분석:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[wordpress 서비스]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

image: wordpress:6.3
└─ Docker Hub의 WordPress 공식 이미지

restart: always
└─ 컨테이너 중지 시 자동 재시작
   ├─ no: 재시작 안 함
   ├─ always: 항상 재시작
   ├─ on-failure: 오류 시만 재시작
   └─ unless-stopped: 수동 중지 전까지 재시작

ports:
  - 127.0.0.1:8080:80
└─ 호스트 8080 → 컨테이너 80

environment:
  WORDPRESS_DB_HOST: db
  └─ 서비스명이 호스트명으로 작동
     db 컨테이너를 "db"로 접근 가능

  WORDPRESS_DB_USER: exampleuser
  WORDPRESS_DB_PASSWORD: examplepass
  WORDPRESS_DB_NAME: exampledb
  └─ MariaDB 연결 정보

volumes:
  - wordpress:/var/www/html
└─ 명명된 볼륨 마운트
   WordPress 파일 영속화

[db 서비스]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

environment:
  MYSQL_DATABASE: exampledb
  └─ 초기 데이터베이스 생성

  MYSQL_USER: exampleuser
  MYSQL_PASSWORD: examplepass
  └─ 사용자 계정 생성

  MYSQL_RANDOM_ROOT_PASSWORD: '1'
  └─ root 비밀번호 랜덤 생성
     (보안 향상)

volumes:
  - db:/var/lib/mysql
└─ 데이터베이스 데이터 영속화

서비스 간 네트워크 통신:

Compose 네트워크:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[자동 생성된 Docker 네트워크]
    │
    ├─ wordpress 컨테이너
    │  └─ 호스트명: wordpress
    │     └─ WORDPRESS_DB_HOST=db로 접속
    │
    └─ db 컨테이너
       └─ 호스트명: db
          └─ MySQL 3306 포트 리스닝

통신 방식:
wordpress 컨테이너 → db:3306 → MariaDB

특징:
→ 서비스명이 DNS로 작동
→ 같은 Compose 프로젝트 내에서만 통신
→ 외부 노출 없이 내부 통신 가능

볼륨 영속화:

데이터 영속성 보장:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[wordpress 볼륨]
    ↓ 마운트
wordpress 컨테이너: /var/www/html
    ↓ 저장
├─ WordPress 코어 파일
├─ 테마
├─ 플러그인
└─ 업로드 파일

[db 볼륨]
    ↓ 마운트
db 컨테이너: /var/lib/mysql
    ↓ 저장
├─ 데이터베이스 파일
├─ 테이블 데이터
└─ 트랜잭션 로그

결과:
→ docker compose down 해도 데이터 유지
→ 컨테이너 재생성 시 데이터 복원
→ 업그레이드 시에도 데이터 보존

Compose 실행 및 관리

컨테이너 실행:

# compose.yml이 있는 디렉터리에서 실행
docker compose up -d

실행 과정:

docker compose up 동작:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[1단계] 네트워크 생성
    ↓
wordpress_default 네트워크 생성
└─ {프로젝트명}_default 패턴

[2단계] 볼륨 생성
    ↓
wordpress_wordpress 볼륨 생성
wordpress_db 볼륨 생성
└─ {프로젝트명}_{볼륨명} 패턴

프로젝트명 결정:
→ 디렉터리명 사용 (wordpress/)
→ compose.yml의 volumes에서 정의한 이름에 접두사 추가

[3단계] 이미지 다운로드
    ↓
wordpress:6.3 Pull
mariadb:11.1 Pull

[4단계] 컨테이너 생성
    ↓
wordpress_db_1 생성 (먼저)
wordpress_wordpress_1 생성 (의존성 고려)
└─ {프로젝트명}_{서비스명}_{인스턴스} 패턴

[5단계] 컨테이너 시작
    ↓
db 컨테이너 시작
wordpress 컨테이너 시작

[-d 옵션]
→ Detached 모드 (백그라운드 실행)
→ 로그 출력 없이 즉시 반환

네이밍 규칙 요약:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
→ 컨테이너: {프로젝트명}_{서비스명}_{번호}
→ 볼륨: {프로젝트명}_{볼륨명}
→ 네트워크: {프로젝트명}_{네트워크명}
→ 프로젝트명: 디렉터리명 (기본값)

상태 확인:

# 실행 중인 컨테이너 확인
docker compose ps

# 로그 확인
docker compose logs

# 특정 서비스 로그
docker compose logs wordpress

# 실시간 로그 스트리밍
docker compose logs -f

서비스 접속:

# 브라우저에서 접속
# http://127.0.0.1:8080

# 또는 PowerShell에서 확인 (보안 경고 없이)
Invoke-WebRequest -Uri http://127.0.0.1:8080 -UseBasicParsing

WordPress 초기 설정:

브라우저 접속 후:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

1. 언어 선택
2. 사이트 정보 입력
   ├─ 사이트 제목
   ├─ 관리자 ID
   └─ 비밀번호
3. WordPress 설치 완료
4. 데이터베이스 연결 자동 설정
   (compose.yml의 환경 변수 사용)

서비스 중지 및 삭제:

# 컨테이너 중지 및 삭제
docker compose down

# 볼륨까지 삭제 (주의: 데이터 손실)
docker compose down -v

down 명령어 동작:

docker compose down:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[기본 down]
    ↓
컨테이너 중지 및 삭제
네트워크 삭제
볼륨은 유지 ← 데이터 보존

[down -v]
    ↓
컨테이너 삭제
네트워크 삭제
볼륨도 삭제 ← 데이터 손실

선택:
→ 개발 중: down (볼륨 유지)
→ 완전 초기화: down -v

Compose 고급 기능

유용한 Compose 명령어:

# 이미지 빌드만 실행
docker compose build

# 특정 서비스만 실행
docker compose up -d wordpress

# 서비스 스케일링
docker compose up -d --scale wordpress=3

# 컨테이너 재시작
docker compose restart

# 서비스 중지 (삭제하지 않음)
docker compose stop

# 서비스 시작 (기존 컨테이너)
docker compose start

# 실행 중인 컨테이너에서 명령어 실행
docker compose exec wordpress bash
docker compose exec db mysql -u root -p

Compose 파일 확장 예시:

# 더 복잡한 구성 예시
services:
  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - wordpress

  wordpress:
    image: wordpress:6.3
    restart: always
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: ${DB_USER}  # 환경 변수 사용
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
    volumes:
      - wordpress:/var/www/html
      - ./uploads.ini:/usr/local/etc/php/conf.d/uploads.ini
    depends_on:
      db:
        condition: service_healthy  # 헬스체크 대기

  db:
    image: mariadb:11.1
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: wordpress
    volumes:
      - db:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:alpine
    restart: always

volumes:
  wordpress:
  db:

networks:
  default:
    driver: bridge

환경 변수 파일 (.env):

# .env 파일 생성
@"
DB_USER=wpuser
DB_PASSWORD=secure_password
MYSQL_ROOT_PASSWORD=root_secure_password
"@ | Set-Content .env
용어 정리

YAML: 사람이 읽기 쉬운 데이터 직렬화 형식. 들여쓰기로 계층 구조 표현하며 compose.yml, Kubernetes 설정 등에 사용됨.

헬스체크 (Health Check): 컨테이너/서비스의 정상 동작 여부 확인. 주기적으로 상태 점검 명령을 실행함.

depends_on: Compose에서 서비스 시작 순서 지정. 의존하는 서비스가 먼저 시작됨.


핵심 요약

다양한 컨테이너 실행 방법 정리:

2.2장 핵심 개념:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[파일 공유 및 데이터 유지]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

바인드 마운트:
docker run -v /host/path:/container/path myapp
→ 호스트 경로 직접 지정
→ 개발 환경 소스 코드 반영
→ 로그, 설정 파일 공유

볼륨:
docker run -v volume-name:/container/path myapp
→ 도커가 위치 관리
→ 컨테이너 간 데이터 공유
→ 영속성 보장

선택 기준:
├─ 개발: 바인드 마운트 (실시간 반영)
└─ 프로덕션: 볼륨 (안정성)

[포트 공개]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

포트 포워딩:
docker run -p 127.0.0.1:8080:80 nginx
→ 호스트 포트를 컨테이너 포트로 연결
→ 외부에서 컨테이너 서비스 접근

보안:
├─ 127.0.0.1: 로컬만 (권장)
├─ 0.0.0.0: 모든 IP (주의)
└─ 필요한 포트만 최소 공개

[Docker Compose]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

다중 컨테이너 관리:
docker compose up -d
→ YAML 파일로 전체 구성 정의
→ 명령어 1개로 모든 서비스 실행
→ 의존성 자동 처리

주요 명령어:
├─ up: 실행
├─ down: 중지 및 삭제
├─ ps: 상태 확인
├─ logs: 로그 확인
└─ exec: 컨테이너 내부 명령 실행

사용 시나리오:
├─ 개발 환경 구성
├─ 마이크로서비스 로컬 테스트
└─ 소규모 프로덕션 배포

vs Kubernetes:
├─ Compose: 단일 머신
└─ Kubernetes: 다중 머신 클러스터

실무 팁:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[개발 환경]
→ Compose로 전체 스택 실행
→ 바인드 마운트로 코드 반영
→ 127.0.0.1로 포트 제한

[프로덕션]
→ 볼륨으로 데이터 영속화
→ restart: always 설정
→ 환경 변수로 설정 분리
→ 헬스체크 구성

결론:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
→ 바인드 마운트/볼륨: 데이터 관리
→ 포트 공개: 네트워크 통신
→ Compose: 복잡도 관리
→ 조합하여 실무 환경 구축

참고 자료

공식 문서:

Compose 관련: